package cn.xjfcloud.onedriveserver.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.StringUtils;

import com.fasterxml.jackson.databind.ObjectMapper;

import cn.xjfcloud.onedriveserver.dao.ApiConfigMapper;
import cn.xjfcloud.onedriveserver.pojo.InitConfig;
import cn.xjfcloud.onedriveserver.pojo.dto.ApiConfig;
import cn.xjfcloud.onedriveserver.util.ApiUtil;

@Service
@Transactional
public class ApiConfigService {

	@Autowired
	private ApiConfigMapper apiConfigMapper;
	@Autowired
	private InitConfig initConfig;
	@Autowired
	private ApiConfigService apiConfigService;

	private static final Logger LOG = LoggerFactory.getLogger(ApiConfigService.class);
	private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

	@Cacheable(value = "apiconfig", key = "#id")
	public ApiConfig getApiConfigById(Integer id) {
		return apiConfigMapper.getApiConfigById(id);
	}
	
	@CachePut(value = "apiconfig", key = "#id")
	public ApiConfig getApiConfigByIdNoCache(Integer id) {
		return apiConfigMapper.getApiConfigById(id);
	}

	/**
	 * 检查accesstoken的状态
	 * 
	 * @param id
	 * @return 0数据库中无记录，1记录存在但是过期，2记录存在且最新
	 */
	public Integer checkTokenStatus(Integer id) {
		ApiConfig apiConfig = apiConfigService.getApiConfigById(id);
		String accessToken = apiConfig.getAccessToken();
		if (StringUtils.isEmpty(accessToken)) {
			return 0;
		} else {
			Date getAccessTokenTime = apiConfig.getGetAccessTokenTime();
			Date now = new Date();
			if (now.getTime() - getAccessTokenTime.getTime() > apiConfig.getExpireTime() * 1000) {
				return 1;
			} else {
				return 2;
			}
		}
	}

	/**
	 * 确定url可用,返回值用integer方便判断缓存
	 * 
	 * @param id
	 * @return
	 */
	@CacheEvict(value = "apiconfig", allEntries = false, key = "#id", condition ="#result != 2")
	public Integer makeTokenUseful(Integer id) {
		Integer tokenStatus = apiConfigService.checkTokenStatus(id);
		if(tokenStatus == 0) {
			return 0;
		}else if(tokenStatus == 1){
			if (apiConfigService.getTokenByRefreshToken(id) == false) {
				return 0;
			}else {
				return 1;
			}
		}else {
			return 2;
		}
	}

	/**
	 * 根据refresh_token获取access_token
	 * 
	 * @param id
	 * @return false 获取失败 true 获取成功
	 */
	@CacheEvict(value = "apiconfig", allEntries = true, beforeInvocation = true)
	public Boolean getTokenByRefreshToken(Integer id) {
		ApiConfig apiConfig = apiConfigService.getApiConfigById(id);
		String refreshToken = apiConfig.getRefreshToken();
		try {
			if (StringUtils.isEmpty(refreshToken)) {
				return false;
			} else {
				String result = ApiUtil.getTokenByRefreshToken(apiConfig);
				HashMap<String, Object> resultMap = OBJECT_MAPPER.readValue(result, HashMap.class);
				if (null == resultMap.get("error") || "".equals(resultMap.get("error"))) {
					apiConfig.setAccessToken((String) resultMap.get("access_token"));
					apiConfig.setRefreshToken((String) resultMap.get("refresh_token"));
					apiConfig.setExpireTime((Integer) resultMap.get("expires_in"));
					apiConfig.setGetAccessTokenTime(new Date());
					apiConfigMapper.updateApiConfigById(apiConfig);
					return true;
				} else {
					LOG.error("getTokenByRefreshToken---->" + result);
					return false;
				}
			}
		} catch (Exception e) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			LOG.error("getTokenByRefreshToken---->", e);
			return false;
		}
	}

	/**
	 * 利用code获取token
	 * 
	 * @param code
	 * @param id
	 * @return
	 */
	@CacheEvict(value = "apiconfig", allEntries = true, beforeInvocation = true)
	public Boolean getTokenByCode(String code, Integer id) {
		try {
			ApiConfig apiConfig = apiConfigService.getApiConfigById(id);
			String result = ApiUtil.getAuthTokenAndReFreshToken(code, apiConfig);
			HashMap<String, Object> authMap;
			authMap = OBJECT_MAPPER.readValue(result, HashMap.class);
			if (null == authMap.get("error") || "".equals(authMap.get("error"))) {
				// 验证通过
				String accessToken = (String) authMap.get("access_token");
				apiConfig.setAccessToken(accessToken);
				String refreshToken = (String) authMap.get("refresh_token");
				apiConfig.setRefreshToken(refreshToken);
				apiConfig.setExpireTime((int) authMap.get("expires_in"));
				apiConfig.setGetAccessTokenTime(new Date());
				// 添加到数据库
				apiConfig.setId(id);
				apiConfigMapper.updateApiConfigById(apiConfig);
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			e.printStackTrace();
			LOG.error("getTokenByCode---->", e);
			return false;
		}
	}

	/**
	 * 获取一个apiConfig,目前为随机
	 * 
	 * @return
	 */
	public ApiConfig getOneApiConfig() {
		List<Integer> clientIds = initConfig.getClientId();
		Random random = new Random();
		int n = random.nextInt(clientIds.size());
		Integer clientId = clientIds.get(n);
		ApiConfig apiConfig = apiConfigService.getApiConfigById(clientId);
		return apiConfig;
	}
}
